using WeatherSystem.API.Models;
using WeatherSystem.API.Services;
using WeatherSystem.API.Repositories;
using WeatherSystem.API.CQRS;
using WeatherSystem.API.CQRS.Commands;
using WeatherSystem.API.CQRS.Queries;
using WeatherSystem.API.Specifications;
using Microsoft.Extensions.Caching.Memory;

namespace WeatherSystem.API.BackgroundJobs
{
    /// <summary>
    /// 后台作业任务执行服务实现
    /// </summary>
    public class BackgroundJobTaskService : IBackgroundJobTaskService
    {
        private readonly IUnitOfWork _unitOfWork;
        private readonly IWeatherService _weatherService;
        private readonly IStatisticsService _statisticsService;
        private readonly IMediator _mediator;
        private readonly ICacheService _cacheService;
        private readonly IMemoryCache _memoryCache;
        private readonly ILogger<BackgroundJobTaskService> _logger;

        public BackgroundJobTaskService(
            IUnitOfWork unitOfWork,
            IWeatherService weatherService,
            IStatisticsService statisticsService,
            IMediator mediator,
            ICacheService cacheService,
            IMemoryCache memoryCache,
            ILogger<BackgroundJobTaskService> logger)
        {
            _unitOfWork = unitOfWork;
            _weatherService = weatherService;
            _statisticsService = statisticsService;
            _mediator = mediator;
            _cacheService = cacheService;
            _memoryCache = memoryCache;
            _logger = logger;
        }

        public async Task<JobExecutionResult> ExecuteDataCollectionAsync()
        {
            var startTime = DateTime.UtcNow;
            var result = new JobExecutionResult { StartTime = startTime };

            try
            {
                _logger.LogInformation("开始执行数据采集任务");
                
                var cities = await _unitOfWork.WeatherData.GetAllAsync();
                var processedCount = 0;
                var errors = new List<string>();

                foreach (var city in cities.Cast<City>())
                {
                    try
                    {
                        var command = new CollectWeatherDataCommand { CityId = city.Id };
                        await _mediator.SendAsync(command);
                        processedCount++;
                        
                        _logger.LogDebug("成功采集城市 {CityName} 的天气数据", city.Name);
                    }
                    catch (Exception ex)
                    {
                        var errorMsg = $"采集城市 {city.Name} 数据失败: {ex.Message}";
                        errors.Add(errorMsg);
                        _logger.LogWarning(ex, errorMsg);
                    }
                }

                result.EndTime = DateTime.UtcNow;
                result.ProcessedCount = processedCount;
                result.Success = errors.Count < cities.Count() / 2; // 如果超过一半失败则认为任务失败
                result.Message = result.Success 
                    ? $"数据采集完成，成功处理 {processedCount} 个城市"
                    : $"数据采集部分失败，成功 {processedCount} 个，失败 {errors.Count} 个";
                
                result.Data["Errors"] = errors;
                result.Data["TotalCities"] = cities.Count();

                _logger.LogInformation("数据采集任务完成，耗时: {Duration}, 处理数量: {Count}", 
                    result.Duration, result.ProcessedCount);

                return result;
            }
            catch (Exception ex)
            {
                result.EndTime = DateTime.UtcNow;
                result.Success = false;
                result.Message = $"数据采集任务执行失败: {ex.Message}";
                _logger.LogError(ex, "数据采集任务执行失败");
                return result;
            }
        }

        public async Task<JobExecutionResult> ExecuteCityDataCollectionAsync(Guid cityId)
        {
            var startTime = DateTime.UtcNow;
            var result = new JobExecutionResult { StartTime = startTime };

            try
            {
                _logger.LogInformation("开始执行城市数据采集任务，城市ID: {CityId}", cityId);

                var command = new CollectWeatherDataCommand { CityId = cityId };
                var weatherData = await _mediator.SendAsync(command);

                result.EndTime = DateTime.UtcNow;
                result.ProcessedCount = 1;
                result.Success = true;
                result.Message = "城市天气数据采集成功";
                result.Data["WeatherDataId"] = weatherData.Id;
                result.Data["CityId"] = cityId;

                _logger.LogInformation("城市数据采集任务完成，城市ID: {CityId}, 耗时: {Duration}", 
                    cityId, result.Duration);

                return result;
            }
            catch (Exception ex)
            {
                result.EndTime = DateTime.UtcNow;
                result.Success = false;
                result.Message = $"城市数据采集失败: {ex.Message}";
                result.Data["CityId"] = cityId;
                _logger.LogError(ex, "城市数据采集任务执行失败，城市ID: {CityId}", cityId);
                return result;
            }
        }

        public async Task<JobExecutionResult> ExecuteStatisticsGenerationAsync()
        {
            var startTime = DateTime.UtcNow;
            var result = new JobExecutionResult { StartTime = startTime };

            try
            {
                _logger.LogInformation("开始执行统计生成任务");

                await _weatherService.GenerateDailyStatisticsAsync();

                result.EndTime = DateTime.UtcNow;
                result.ProcessedCount = 1;
                result.Success = true;
                result.Message = "统计数据生成成功";

                _logger.LogInformation("统计生成任务完成，耗时: {Duration}", result.Duration);

                return result;
            }
            catch (Exception ex)
            {
                result.EndTime = DateTime.UtcNow;
                result.Success = false;
                result.Message = $"统计生成失败: {ex.Message}";
                _logger.LogError(ex, "统计生成任务执行失败");
                return result;
            }
        }

        public async Task<JobExecutionResult> ExecuteDataCleanupAsync()
        {
            var startTime = DateTime.UtcNow;
            var result = new JobExecutionResult { StartTime = startTime };

            try
            {
                _logger.LogInformation("开始执行数据清理任务");

                // 清理30天前的天气数据（保留重要的统计数据）
                var cutoffDate = DateTime.UtcNow.AddDays(-30);
                var oldDataQuery = await _unitOfWork.WeatherData.GetBySpecificationAsync(new WeatherDataWithCitySpecification(null, null, cutoffDate, null));
                var oldDataList = oldDataQuery.ToList();

                var processedCount = 0;
                await _unitOfWork.BeginTransactionAsync();

                try
                {
                    foreach (var oldData in oldDataList)
                    {
                        // 只删除非重要数据，保留每日统计摘要
                        if (!IsImportantData(oldData))
                        {
                            await _unitOfWork.WeatherData.DeleteAsync(oldData);
                            processedCount++;
                        }
                    }

                    await _unitOfWork.SaveChangesAsync();
                    await _unitOfWork.CommitTransactionAsync();
                }
                catch
                {
                    await _unitOfWork.RollbackTransactionAsync();
                    throw;
                }

                // 清理内存缓存
                if (_memoryCache is MemoryCache mc)
                {
                    mc.Compact(0.2); // 清理20%的缓存
                }

                result.EndTime = DateTime.UtcNow;
                result.ProcessedCount = processedCount;
                result.Success = true;
                result.Message = $"数据清理完成，清理了 {processedCount} 条记录";
                result.Data["CutoffDate"] = cutoffDate;
                result.Data["TotalOldRecords"] = oldDataList.Count;

                _logger.LogInformation("数据清理任务完成，清理记录数: {Count}, 耗时: {Duration}", 
                    processedCount, result.Duration);

                return result;
            }
            catch (Exception ex)
            {
                result.EndTime = DateTime.UtcNow;
                result.Success = false;
                result.Message = $"数据清理失败: {ex.Message}";
                _logger.LogError(ex, "数据清理任务执行失败");
                return result;
            }
        }

        public async Task<JobExecutionResult> ExecuteWeatherReportGenerationAsync(Guid cityId, DateTime startDate, DateTime endDate)
        {
            var startTime = DateTime.UtcNow;
            var result = new JobExecutionResult { StartTime = startTime };

            try
            {
                _logger.LogInformation("开始生成天气报告，城市ID: {CityId}, 时间范围: {StartDate} - {EndDate}", 
                    cityId, startDate, endDate);

                // 获取天气历史数据
                var historyData = await _weatherService.GetWeatherHistoryAsDictionaryAsync(cityId, startDate, endDate);
                
                // 生成报告摘要
                var report = new
                {
                    CityId = cityId,
                    StartDate = startDate,
                    EndDate = endDate,
                    RecordCount = historyData.Count,
                    GeneratedAt = DateTime.UtcNow,
                    Summary = GenerateWeatherSummary(historyData)
                };

                result.EndTime = DateTime.UtcNow;
                result.ProcessedCount = historyData.Count;
                result.Success = true;
                result.Message = "天气报告生成成功";
                result.Data["Report"] = report;

                _logger.LogInformation("天气报告生成完成，城市ID: {CityId}, 记录数: {Count}, 耗时: {Duration}", 
                    cityId, historyData.Count, result.Duration);

                return result;
            }
            catch (Exception ex)
            {
                result.EndTime = DateTime.UtcNow;
                result.Success = false;
                result.Message = $"天气报告生成失败: {ex.Message}";
                result.Data["CityId"] = cityId;
                _logger.LogError(ex, "天气报告生成任务执行失败，城市ID: {CityId}", cityId);
                return result;
            }
        }

        public async Task<JobExecutionResult> ExecuteBulkDataSimulationAsync(int recordsPerCity, double baseTemperature)
        {
            var startTime = DateTime.UtcNow;
            var result = new JobExecutionResult { StartTime = startTime };

            try
            {
                _logger.LogInformation("开始批量数据模拟，每城市记录数: {Records}, 基础温度: {Temperature}", 
                    recordsPerCity, baseTemperature);

                var command = new SimulateWeatherDataCommand 
                { 
                    Count = recordsPerCity,
                    BaseTemperature = baseTemperature
                };
                
                var simulationResult = await _mediator.SendAsync(command);

                result.EndTime = DateTime.UtcNow;
                result.ProcessedCount = simulationResult.TotalDataGenerated;
                result.Success = true;
                result.Message = $"批量数据模拟完成，生成了 {simulationResult.TotalDataGenerated} 条记录";
                result.Data["SimulationResult"] = simulationResult;

                _logger.LogInformation("批量数据模拟任务完成，生成记录数: {Count}, 耗时: {Duration}", 
                    simulationResult.TotalDataGenerated, result.Duration);

                return result;
            }
            catch (Exception ex)
            {
                result.EndTime = DateTime.UtcNow;
                result.Success = false;
                result.Message = $"批量数据模拟失败: {ex.Message}";
                result.Data["RecordsPerCity"] = recordsPerCity;
                result.Data["BaseTemperature"] = baseTemperature;
                _logger.LogError(ex, "批量数据模拟任务执行失败");
                return result;
            }
        }

        public async Task<JobExecutionResult> ExecuteCacheWarmupAsync()
        {
            var startTime = DateTime.UtcNow;
            var result = new JobExecutionResult { StartTime = startTime };

            try
            {
                _logger.LogInformation("开始执行缓存预热任务");

                var processedCount = 0;

                // 预热城市数据
                var citiesQuery = new GetCitiesQuery { Page = 1, PageSize = 100 };
                await _mediator.QueryAsync(citiesQuery);
                processedCount++;

                // 预热最新天气数据
                var cities = await _unitOfWork.WeatherData.GetAllAsync();
                foreach (var city in cities.Cast<City>().Take(20)) // 只预热前20个城市避免过长时间
                {
                    var weatherQuery = new GetWeatherDataByIdQuery();
                    var latestData = await _unitOfWork.WeatherData.GetLatestByCityAsync(city.Id);
                    if (latestData != null)
                    {
                        weatherQuery.Id = latestData.Id;
                        await _mediator.QueryAsync(weatherQuery);
                        processedCount++;
                    }
                }

                // 预热统计数据缓存
                var statsQuery = new GetWeatherStatsQuery 
                { 
                    StartDate = DateTime.UtcNow.AddDays(-7),
                    EndDate = DateTime.UtcNow
                };
                await _mediator.QueryAsync(statsQuery);
                processedCount++;

                result.EndTime = DateTime.UtcNow;
                result.ProcessedCount = processedCount;
                result.Success = true;
                result.Message = $"缓存预热完成，预热了 {processedCount} 个缓存项";

                _logger.LogInformation("缓存预热任务完成，预热项数: {Count}, 耗时: {Duration}", 
                    processedCount, result.Duration);

                return result;
            }
            catch (Exception ex)
            {
                result.EndTime = DateTime.UtcNow;
                result.Success = false;
                result.Message = $"缓存预热失败: {ex.Message}";
                _logger.LogError(ex, "缓存预热任务执行失败");
                return result;
            }
        }

        private bool IsImportantData(WeatherDataEntry data)
        {
            // 判断是否为重要数据（如每日统计摘要）
            // 这里可以根据业务规则自定义
            return data.Source?.Contains("Summary") == true || 
                   data.Source?.Contains("Daily") == true;
        }

        private object GenerateWeatherSummary(List<Dictionary<string, object>> historyData)
        {
            if (historyData == null || !historyData.Any())
            {
                return new { Message = "无数据可分析" };
            }

            try
            {
                // 简单的天气统计分析
                var temperatures = new List<double>();
                var humidities = new List<double>();

                foreach (var data in historyData)
                {
                    if (data.ContainsKey("Temperature") && double.TryParse(data["Temperature"]?.ToString(), out double temp))
                    {
                        temperatures.Add(temp);
                    }
                    if (data.ContainsKey("Humidity") && double.TryParse(data["Humidity"]?.ToString(), out double humidity))
                    {
                        humidities.Add(humidity);
                    }
                }

                return new
                {
                    RecordCount = historyData.Count,
                    Temperature = temperatures.Any() ? new
                    {
                        Average = Math.Round(temperatures.Average(), 2),
                        Min = temperatures.Min(),
                        Max = temperatures.Max()
                    } : null,
                    Humidity = humidities.Any() ? new
                    {
                        Average = Math.Round(humidities.Average(), 2),
                        Min = humidities.Min(),
                        Max = humidities.Max()
                    } : null
                };
            }
            catch
            {
                return new { Message = "统计分析失败" };
            }
        }
    }
}